package com.exercise.ThreadCommunication;

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerExample {
    public static void main(String[] args) {
        // 创建一个缓冲区对象，容量为5
        // Create a buffer with capacity 5
        Buffer buffer = new Buffer(5);

        // 创建生产者线程
        // Create producer thread
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    buffer.produce(i); // 生产一个数据项 / Produce an item
                    Thread.sleep(1000); // 模拟生产耗时 / Simulate production delay
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态 / Restore interrupt status
            }
        }, "Producer");

        // 创建消费者线程
        // Create consumer thread
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    buffer.consume(); // 消费一个数据项 / Consume an item
                    Thread.sleep(2000); // 模拟消费耗时 / Simulate consumption delay
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // 恢复中断状态 / Restore interrupt status
            }
        }, "Consumer");

        // 启动线程 / Start both threads
        producer.start();
        consumer.start();
    }
}

// 缓冲区类：生产者将数据放入队列，消费者从中取出
// Buffer class: producers put items, consumers take items
class Buffer {
    private final Queue<Integer> queue; // 存储数据项的队列 / Shared queue (buffer)
    private final int capacity;         // 缓冲区最大容量 / Maximum capacity of the buffer

    public Buffer(int capacity) {
        this.queue = new LinkedList<>(); // 初始化队列 / Initialize queue
        this.capacity = capacity;
    }

    // 生产方法：将数据放入队列
    // Produce method: add item to the buffer
    public void produce(int item) throws InterruptedException {
        synchronized (this) { // 加锁，确保线程安全 / Lock to ensure thread safety
            while (queue.size() == capacity) {
                // 如果缓冲区满了，进入等待 / Wait if the buffer is full
                System.out.println(Thread.currentThread().getName() + " waiting, buffer is full");
                wait(); // 释放锁，等待被唤醒 / Release lock and wait
            }

            // 添加数据到缓冲区 / Add item to buffer
            queue.offer(item);
            System.out.println(Thread.currentThread().getName() + " produced: " + item);

            // 通知等待的消费者线程 / Notify waiting consumers
            notifyAll();
        }
    }

    // 消费方法：从队列中取出数据
    // Consume method: remove item from buffer
    public void consume() throws InterruptedException {
        synchronized (this) { // 加锁，确保线程安全 / Lock to ensure thread safety
            while (queue.isEmpty()) {
                // 如果缓冲区为空，进入等待 / Wait if buffer is empty
                System.out.println(Thread.currentThread().getName() + " waiting, buffer is empty");
                wait(); // 释放锁，等待被唤醒 / Release lock and wait
            }

            // 从队列头部取出数据 / Remove item from buffer
            int item = queue.poll();
            System.out.println(Thread.currentThread().getName() + " consumed: " + item);

            // 通知等待的生产者线程 / Notify waiting producers
            notifyAll();
        }
    }
}